package ui;

import java.io.*;
import java.awt.TextArea;
import java.awt.Font;

/**
* This class combines the data model and the view to inspect and
* edit a series of x-y value pairs.
* The model stores both a raw text representation and the same data
* converted into an array of points.
* The raw text is stored because the user may embed comments into
* his input. These comments would get lost if only the numeric point
* data was stored.
*
* @version 1.0
* @author Hans U. Gerber (<a href="mailto:gerber@ifh.ee.ethz.ch">gerber@ifh.ee.ethz.ch</a>)
*/
public class PointsUI extends TextArea implements Validatable {
	private String label;
	private RealPoint[] data;
	private String rawText;

	public PointsUI(String label, String rawText) {
		super();
		setFont(new Font("Courier", Font.PLAIN, 10));
		this.label = label;
		this.rawText = rawText;
		this.data = read(rawText);
		display();
	}

	public String getLabel() { return label; }

	public void display() {
		setText(rawText);
	}

	public RealPoint[] get() {
		return data;
	}

	/**
	* Checks if the contents of the edit field are valid,
	* i.e. the user entered at least 10 x-y pairs.
	* @return <code>null</code> if valid, an error message
	*		otherwise.
	*/
	public String check() {
		RealPoint[] temp = read(getText());
		boolean ok = (temp != null && temp.length >= 10);
		if (ok) {
			return null;
		} else {
			return "\"" + label + "\" must contain at least 10 x-y-value pairs.";
		}
	}

	/**
	* Copies the raw text and the x-y values (read from the same raw text)
	* from the edit field into the model. This method assumes that the
	* contents of the field have already been validated.
	*/
	public void accept() {
		rawText = getText();
		data = read(rawText);
	}

	static final int MAX_NR_OF_FITNESS_CASES = 100;

	/**
	* Decodes the contents of the edit field into a series of x-y value
	* pairs.<br>
	* Note that the strean tokenizer used here does not understand numbers
	* with an exponent (like 1.23E+3).
	* @return an array of x-y points
	*/
	private RealPoint[] read(String s) {
		StringBufferInputStream stream = new StringBufferInputStream(s);
		StreamTokenizer tokenizer = new StreamTokenizer(stream);
		RealPoint[] temp = new RealPoint[MAX_NR_OF_FITNESS_CASES];
		int count = 0;
		try {
			int token;
			do {
				double x;
				double y;
				token = tokenizer.nextToken();
				if (token == StreamTokenizer.TT_NUMBER) {
					x = tokenizer.nval;
					token =	tokenizer.nextToken();
					if (token	== StreamTokenizer.TT_NUMBER) {
						y = tokenizer.nval;
						temp[count] = new RealPoint(x, y);
						count++;
					}
				}
			} while (count < MAX_NR_OF_FITNESS_CASES && token != StreamTokenizer.TT_EOF);
		} catch (Exception e) {
			;
		}
		RealPoint[] result = new RealPoint[count];
		System.arraycopy(temp, 0, result, 0, count);
		return result;
	}

}

